"""
	实现单链表的构建和功能操作
"""


# 创建 节点类
class Node:
	"""
		节点类:
			思路 : 生成单链表,通过实例化的对象就代表一个链表, nxt代表上一个实例对象
                可以调用具体的操作方法完成各种功能
	"""

	def __init__(self, val, nxt=None):
		self.val = val  # 存储有用的数据
		self.nxt = nxt  # 存储实例之间的关系, 下一个节点关系

	def __str__(self):
		return f"{self.val}, {self.nxt}"


class LinkList:
	"""
	单链表类(线性存储列表简称), 生成对象可以进行增删改查操作
		具体操作通过调用具体方法完成
	"""

	def __init__(self):
		"""
		初始化链表,标记一个链表的开端,以便于获取后续的节点
		"""
		self.head = Node(None)  # 关联节点

	# 通过list_ 为链表添加一组节点 增
	def init_list(self, list_):
		"""
		通过list_ 为链表添加一组节点
		:param list_: 列表
		:return: wu
		"""
		p = self.head
		for item in list_:
			p.nxt = Node(item)
			p = p.nxt   # p先后移动一位

	# 遍历链表
	def show(self):
		"""
		变量链表
		:return:
		"""
		ps = self.head.nxt   # 第一个有效节点
		while ps is not None:  # 判断对象相不相等的时候用, is(是不是) is not(不是), 判断值用<,>,=....
			print(ps.val, "ps.nxt")
			ps = ps.nxt  # p先后移动一位

	# 判断链表为空'
	def is_empty(self):
		if self.head.nxt is None:
			return True
		else:
			return False

	# 清空链表
	def clear(self):
		self.head.nxt = None

	# 链表尾部插入
	def end_append(self, value):
		p = self.head
		while p.nxt is not None:
			p = p.nxt
		p.nxt = Node(value)

	# 链表头部插入
	def head_insert(self, value):
		node = Node(value)  # 生成节点
		node.nxt = self.head.nxt    # 指向head的下一个节点
		self.head.nxt = node        #

	# 指定插入位置
	def insert(self, index, value):
		so = self.head           # 设置个so 移动到待插入位置的前一个
		for i in range(index):
			if so.nxt is not None:   # 如果index超出了最大范围跳出循环
				break
			so = so.nxt
		# 插入节点
		node = Node(value)
		node.nxt = so.nxt
		so.nxt = node

	# 删除节点
	def remove(self, value):
		so = self.head
		# so 移动,待删除节点上一个
		while so.nxt is not None and so.nxt.val != value:
			so = so.nxt
		# 结束循环必然两个条件其一为假
		if so.nxt is None:
			raise ValueError(f"{value} 不在链表中!")
		else:
			so.nxt = so.nxt.nxt

	# 获取某个节点的值 (通过索引获取)
	def get_index(self, index):
		if index < 0:   # 因为Python不支持负数,所有要加个判断不能为负数
			raise IndexError("索引超出范围!")

		p = self.head.nxt
		# 循环移动p
		for i in range(index):
			if p is None:
				raise IndexError("索引超出范围!")
			p = p.nxt
		return p.val

if __name__ == '__main__':
	l = LinkList()
	# l.head.nxt = Node(1)  # 实例化之后在关联传值一次
	# print(l.head)
	l.init_list([2, 5, 3, 8, 6])
	l.show()
